package com.adopapa.nezhacloud.ddd.conf;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class CommentIntegrator implements Integrator {

	private Logger logger = LoggerFactory.getLogger(getClass());

	public static final CommentIntegrator INSTANCE = new CommentIntegrator();

	@Override
	public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {

	}

	@Override
	public void integrate(Metadata metadata, BootstrapContext bootstrapContext,
			SessionFactoryImplementor sessionFactory) {
		processComment(metadata);
	}

	/**
	 * Process comment annotation.
	 *
	 * @param metadata process annotation of this {@code Metadata}.
	 */
	private void processComment(Metadata metadata) {
		for (PersistentClass persistentClass : metadata.getEntityBindings()) {
			// Process the Comment annotation is applied to Class
			Class<?> clz = persistentClass.getMappedClass();
			if (clz.isAnnotationPresent(Comment.class)) {
				Comment comment = clz.getAnnotation(Comment.class);
				persistentClass.getTable().setComment(comment.value());
				logger.info("设置表注释: {} - {}", persistentClass.getTable(), comment.value());
			}

			// Process Comment annotations of identifier.
			Property identifierProperty = persistentClass.getIdentifierProperty();
			if (identifierProperty != null) {
				fieldComment(persistentClass, identifierProperty.getName());
			} else {
				org.hibernate.mapping.Component component = persistentClass.getIdentifierMapper();
				if (component != null) {
					// noinspection unchecked
					List<Property> properties = component.getProperties();
					for (Property property : properties) {
						fieldComment(persistentClass, property.getName());
					}
//                    Iterator<Property> iterator = component.getPropertyIterator();
//                    while (iterator.hasNext()) {
//                        fieldComment(persistentClass, iterator.next().getName());
//                    }
				}
			}
			// Process fields with Comment annotation.
			// noinspection unchecked
			List<Property> properties = persistentClass.getProperties();
			for (Property property : properties) {
				fieldComment(persistentClass, property.getName());
			}
//            Iterator<Property> iterator = persistentClass.getPropertyIterator();
//            while (iterator.hasNext()) {
//                fieldComment(persistentClass, iterator.next().getName());
//            }
		}
	}

	/**
	 * Process @{code comment} annotation of field.
	 *
	 * @param persistentClass Hibernate {@code PersistentClass}
	 * @param columnName      name of field
	 */
	private void fieldComment(PersistentClass persistentClass, String columnName) {
		try {
			Field field = persistentClass.getMappedClass().getDeclaredField(columnName);
			if (field.isAnnotationPresent(Comment.class)) {
				Comment comment = field.getAnnotation(Comment.class);
				List<Column> columns = persistentClass.getProperty(columnName).getColumns();
				if (columns == null || columns.size() == 0) {
					return;
				}
//                String sqlColumnName = persistentClass.getProperty(columnName).getValue().getColumnIterator().next().getText();
//                Iterator<Column> columnIterator = persistentClass.getTable().getColumnIterator();
//                while (columnIterator.hasNext()) {
//                    org.hibernate.mapping.Column column = columnIterator.next();
//                    if (sqlColumnName.equalsIgnoreCase(column.getName())) {
//                        column.setComment(comment.value());
//                        logger.info("设置表字段注释: {} - {} - {}", persistentClass.getTable(), sqlColumnName, comment.value());
//                        break;
//                    }
//                }
				String sqlColumnName = columns.get(0).getText();
				Collection<Column> tableColumns = persistentClass.getTable().getColumns();
				for (Column column : tableColumns) {
					if (sqlColumnName.equalsIgnoreCase(column.getName())) {
						column.setComment(comment.value());
						logger.info("设置表字段注释: {} - {} - {}", persistentClass.getTable(), sqlColumnName,
								comment.value());
						break;
					}
				}
			}
		} catch (NoSuchFieldException | SecurityException ignored) {
		}
	}
}
